//jTDS JDBC Driver for Microsoft SQL Server and Sybase //Copyright (C) 2004 The jTDS Project // //This library is free software; you can redistribute it and/or //modify it under the terms of the GNU Lesser General Public //License as published by the Free Software Foundation; either //version 2.1 of the License, or (at your option) any later version. // //This library is distributed in the hope that it will be useful, //but WITHOUT ANY WARRANTY; without even the implied warranty of //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //Lesser General Public License for more details. // //You should have received a copy of the GNU Lesser General Public //License along with this library; if not, write to the Free Software //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // package net.sourceforge.jtds.jdbc; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import javax.sql.XAConnection; import javax.sql.XADataSource; import javax.transaction.xa.XAException; import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; import net.sourceforge.jtds.jdbc.Messages; import net.sourceforge.jtds.jdbc.Driver; import net.sourceforge.jtds.jdbcx.JtdsDataSource; import net.sourceforge.jtds.jdbcx.JtdsXid; /** * Test suite for XA Distributed Transactions. These tests are derived from * examples found in the following article at * <a href="http://archive.devx.com/java/free/articles/dd_jta/jta-2.asp">DevX</a>. * * @version $Id: XaTest.java,v 1.5 2004-12-03 16:52:09 alin_sinpalean Exp $ */ public class XaTest extends DatabaseTestCase { public XaTest(String name) { super(name); } /** * Obtain an XADataSource. * * @return the <code>XADataSource. * @throws SQLException if an error condition occurs */ public XADataSource getDataSource() throws SQLException { JtdsDataSource xaDS = new JtdsDataSource(); String user = props.getProperty(Messages.get(Driver.USER)); String pwd = props.getProperty(Messages.get(Driver.PASSWORD)); String host = props.getProperty(Messages.get(Driver.SERVERNAME)); String port = props.getProperty(Messages.get(Driver.PORTNUMBER)); String database = props.getProperty(Messages.get(Driver.DATABASENAME)); String xaMode = props.getProperty(Messages.get(Driver.XAEMULATION)); String tds = props.getProperty(Messages.get(Driver.TDS)); String serverType = props.getProperty(Messages.get(Driver.SERVERTYPE)); int portn; try { portn = Integer.parseInt(port); } catch (NumberFormatException e) { portn = 1433; } xaDS.setServerName(host); xaDS.setPortNumber(portn); xaDS.setUser(user); xaDS.setPassword(pwd); xaDS.setDatabaseName(database); xaDS.setXaEmulation(xaMode.equalsIgnoreCase("true")); xaDS.setTds(tds); xaDS.setServerType("2".equals(serverType)? 2: 1); return xaDS; } /** * Test to demonstrate the XA_COMMIT function. * * @throws Exception if an error condition occurs */ public void testXaCommit() throws Exception { Connection con2 = null; XAConnection xaCon = null; try { dropTable("jTDS_XATEST"); Statement stmt = con.createStatement(); stmt.execute("CREATE TABLE jTDS_XATEST (id int primary key, data varchar(255))"); assertNotNull(stmt.executeQuery("SELECT * FROM jTDS_XATEST")); stmt.close(); XADataSource xaDS = getDataSource(); XAResource xaRes; Xid xid; xaCon = xaDS.getXAConnection(); xaRes = xaCon.getXAResource(); con2 = xaCon.getConnection(); stmt = con2.createStatement(); xid = new JtdsXid(new byte[]{0x01}, new byte[]{0x02}); xaRes.start(xid, XAResource.TMNOFLAGS); stmt.executeUpdate("INSERT INTO jTDS_XATEST VALUES (1, 'TEST LINE')"); xaRes.end(xid, XAResource.TMSUCCESS); int ret = xaRes.prepare(xid); if (ret == XAResource.XA_OK) { xaRes.commit(xid, false); } stmt.close(); stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM jTDS_XATEST"); assertNotNull(rs); assertTrue(rs.next()); stmt.close(); } finally { if (con2 != null) { con2.close(); } if (xaCon != null) { xaCon.close(); } dropTable("jTDS_XATEST"); } } /** * Test to demonstrate the single phase XA_COMMIT function. * * @throws Exception if an error condition occurs */ public void testXaOnePhaseCommit() throws Exception { Connection con2 = null; XAConnection xaCon = null; try { dropTable("jTDS_XATEST"); Statement stmt = con.createStatement(); stmt.execute("CREATE TABLE jTDS_XATEST (id int primary key, data varchar(255))"); assertNotNull(stmt.executeQuery("SELECT * FROM jTDS_XATEST")); stmt.close(); XADataSource xaDS = getDataSource(); XAResource xaRes; Xid xid; xaCon = xaDS.getXAConnection(); xaRes = xaCon.getXAResource(); con2 = xaCon.getConnection(); stmt = con2.createStatement(); xid = new JtdsXid(new byte[]{0x01}, new byte[]{0x02}); xaRes.start(xid, XAResource.TMNOFLAGS); stmt.executeUpdate("INSERT INTO jTDS_XATEST VALUES (1, 'TEST LINE')"); xaRes.end(xid, XAResource.TMSUCCESS); xaRes.commit(xid, true); stmt.close(); stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM jTDS_XATEST"); assertNotNull(rs); assertTrue(rs.next()); stmt.close(); } finally { if (con2 != null) { con2.close(); } if (xaCon != null) { xaCon.close(); } dropTable("jTDS_XATEST"); } } /** * Test to demonstrate the use of the XA_ROLLBACK command. * * @throws Exception if an error condition occurs */ public void testXaRollback() throws Exception { Connection con2 = null; XAConnection xaCon = null; try { dropTable("jTDS_XATEST"); Statement stmt = con.createStatement(); stmt.execute("CREATE TABLE jTDS_XATEST (id int primary key, data varchar(255))"); assertNotNull(stmt.executeQuery("SELECT * FROM jTDS_XATEST")); stmt.close(); XADataSource xaDS = getDataSource(); XAResource xaRes; Xid xid; xaCon = xaDS.getXAConnection(); xaRes = xaCon.getXAResource(); con2 = xaCon.getConnection(); stmt = con2.createStatement(); xid = new JtdsXid(new byte[]{0x01}, new byte[]{0x02}); xaRes.start(xid, XAResource.TMNOFLAGS); stmt.executeUpdate("INSERT INTO jTDS_XATEST VALUES (1, 'TEST LINE')"); xaRes.end(xid, XAResource.TMSUCCESS); xaRes.rollback(xid); stmt.close(); stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM jTDS_XATEST"); assertNotNull(rs); assertFalse(rs.next()); stmt.close(); } finally { if (con2 != null) { con2.close(); } if (xaCon != null) { xaCon.close(); } dropTable("jTDS_XATEST"); } } /** * Demonstrate interleaving local transactions and distributed * transactions. * * @throws Exception if an error condition occurs */ public void testLocalTran() throws Exception { if ("true".equalsIgnoreCase(props.getProperty(Messages.get(Driver.XAEMULATION)))) { // Emulation mode does not support suspending transactions. return; } Connection con2 = null; XAConnection xaCon = null; try { dropTable("jTDS_XATEST"); dropTable("jTDS_XATEST2"); Statement stmt = con.createStatement(); stmt.execute("CREATE TABLE jTDS_XATEST (id int primary key, data varchar(255))"); stmt.execute("CREATE TABLE jTDS_XATEST2 (id int primary key, data varchar(255))"); assertNotNull(stmt.executeQuery("SELECT * FROM jTDS_XATEST")); assertNotNull(stmt.executeQuery("SELECT * FROM jTDS_XATEST2")); stmt.close(); XADataSource xaDS = getDataSource(); XAResource xaRes; Xid xid; xaCon = xaDS.getXAConnection(); xaRes = xaCon.getXAResource(); con2 = xaCon.getConnection(); stmt = con2.createStatement(); xid = new JtdsXid(new byte[]{0x01}, new byte[]{0x02}); xaRes.start(xid, XAResource.TMNOFLAGS); stmt.executeUpdate("INSERT INTO jTDS_XATEST VALUES (1, 'TEST LINE')"); xaRes.end(xid, XAResource.TMSUSPEND); stmt.executeUpdate("INSERT INTO jTDS_XATEST2 VALUES (1, 'TEST LINE')"); xaRes.start(xid, XAResource.TMRESUME); stmt.executeUpdate("INSERT INTO jTDS_XATEST VALUES (2, 'TEST LINE 2')"); xaRes.end(xid, XAResource.TMSUCCESS); xaRes.rollback(xid); stmt.close(); stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM jTDS_XATEST"); assertNotNull(rs); assertFalse(rs.next()); rs = stmt.executeQuery("SELECT * FROM jTDS_XATEST2"); assertNotNull(rs); assertTrue(rs.next()); stmt.close(); } finally { if (con2 != null) { con2.close(); } if (xaCon != null) { xaCon.close(); } dropTable("jTDS_XATEST"); dropTable("jTDS_XATEST2"); } } /** * Test to demonstrate the use of the XA_JOIN command. * * @throws Exception if an error condition occurs */ public void testXAJoinTran() throws Exception { if ("true".equalsIgnoreCase(props.getProperty(Messages.get(Driver.XAEMULATION)))) { // Emulation mode does not joining transactions. return; } Connection con2 = null; Connection con3 = null; XAConnection xaCon = null; XAConnection xaCon2 = null; try { dropTable("jTDS_XATEST"); dropTable("jTDS_XATEST2"); Statement stmt = con.createStatement(); stmt.execute("CREATE TABLE jTDS_XATEST (id int primary key, data varchar(255))"); stmt.execute("CREATE TABLE jTDS_XATEST2 (id int primary key, data varchar(255))"); assertNotNull(stmt.executeQuery("SELECT * FROM jTDS_XATEST")); assertNotNull(stmt.executeQuery("SELECT * FROM jTDS_XATEST2")); stmt.close(); XADataSource xaDS = getDataSource(); XAResource xaRes; XAResource xaRes2; Xid xid; xaCon = xaDS.getXAConnection(); xaRes = xaCon.getXAResource(); xaCon2 = xaDS.getXAConnection(); xaRes2 = xaCon2.getXAResource(); con2 = xaCon.getConnection(); con3 = xaCon2.getConnection(); stmt = con2.createStatement(); Statement stmt2 = con3.createStatement(); xid = new JtdsXid(new byte[]{0x01}, new byte[]{0x02}); xaRes.start(xid, XAResource.TMNOFLAGS); stmt.executeUpdate("INSERT INTO jTDS_XATEST VALUES (1, 'TEST LINE')"); assertTrue(xaRes.isSameRM(xaRes2)); xaRes2.start(xid, XAResource.TMJOIN); stmt2.executeUpdate("INSERT INTO jTDS_XATEST2 VALUES (1, 'TEST LINE 2')"); xaRes.end(xid, XAResource.TMSUCCESS); xaRes2.end(xid, XAResource.TMSUCCESS); int ret = xaRes.prepare(xid); if (ret == XAResource.XA_OK) { xaRes.commit(xid, false); } stmt.close(); stmt2.close(); stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM jTDS_XATEST"); assertNotNull(rs); assertTrue(rs.next()); rs = stmt.executeQuery("SELECT * FROM jTDS_XATEST2"); assertNotNull(rs); assertTrue(rs.next()); stmt.close(); } finally { if (con2 != null) { con2.close(); } if (con3 != null) { con3.close(); } if (xaCon != null) { xaCon.close(); } if (xaCon2 != null) { xaCon2.close(); } dropTable("jTDS_XATEST"); dropTable("jTDS_XATEST2"); } } /** * Test to demonstrate the use of the XA_RECOVER command. * * @throws Exception if an error condition occurs */ public void testXARecover() throws Exception { XAConnection xaCon = null; try { dropTable("jTDS_XATEST"); Statement stmt = con.createStatement(); stmt.execute("CREATE TABLE jTDS_XATEST (id int primary key, data varchar(255))"); assertNotNull(stmt.executeQuery("SELECT * FROM jTDS_XATEST")); stmt.close(); XADataSource xaDS = getDataSource(); xaCon = xaDS.getXAConnection(); Connection con2 = xaCon.getConnection(); XAResource xaRes = xaCon.getXAResource(); stmt = con2.createStatement(); Xid xid; xid = new JtdsXid(new byte[]{0x01}, new byte[]{0x02}); xaRes.start(xid, XAResource.TMNOFLAGS); stmt.executeUpdate("INSERT INTO jTDS_XATEST VALUES (1, 'TEST LINE')"); xaRes.end(xid, XAResource.TMSUCCESS); xaRes.prepare(xid); stmt.close(); con2.close(); xaCon.close(); xaCon = xaDS.getXAConnection(); xaRes = xaCon.getXAResource(); Xid[] list = xaRes.recover(XAResource.TMSTARTRSCAN); for (int i = 0; i < list.length; i++) { //System.out.println("Xid="+list[i].toString()); try { xaRes.rollback(list[i]); } catch (XAException e) { // System.out.println("Forgetting"); xaRes.forget(list[i]); } } } finally { if (xaCon != null) { xaCon.close(); } dropTable("jTDS_XATEST"); } } public static void main(String[] args) { junit.textui.TestRunner.run(XaTest.class); } }